// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

package status

import (
	"fmt"

	"github.com/ttacon/chalk"
)

type StatusLevel int

const (
	INFO  StatusLevel = iota // 0
	WARN                     // 1
	ERROR                    // 2
	FATAL                    // 3
)

type Status struct {
	Code    int
	Level   StatusLevel
	Message string
}

func (s Status) Ok() bool {
	return s.Code == 0
}

func NewOk(msg string) Status {
	return Status{0, INFO, msg}
}

func NewWarn(code int, msg string) Status {
	return Status{code, WARN, msg}
}

func NewError(code int, msg string) Status {
	return Status{code, ERROR, msg}
}

func NewFatal(code int, msg string) Status {
	return Status{code, FATAL, msg}
}

func (sl StatusLevel) String() string {
	return [...]string{"INFO", "WARN", "ERROR", "FATAL"}[sl]
}

type StatusOutput interface {
	Print(Status Status)
}

type RawOutput struct{}

func (c RawOutput) Print(status Status) {
	fmt.Println(status.Message)
}

type TerminalOutput struct{}

func (c TerminalOutput) Print(status Status) {
	switch status.Level {
	case INFO:
		fmt.Printf("[%s] %s\n", chalk.Bold.TextStyle(chalk.Green.Color(status.Level.String())), chalk.Green.Color(status.Message))
	case WARN:
		fmt.Printf("[%s] %s\n", chalk.Bold.TextStyle(chalk.Yellow.Color(status.Level.String())), chalk.Yellow.Color(status.Message))
	case ERROR:
		fmt.Println(chalk.Red.Color(status.Message))
		fmt.Printf("[%s] %s\n", chalk.Bold.TextStyle(chalk.Red.Color(status.Level.String())), chalk.Red.Color(status.Message))
	case FATAL:
		st := chalk.Red.NewStyle().WithBackground(chalk.Yellow)
		fmt.Printf("[%s] %s\n", chalk.Bold.TextStyle(chalk.Red.Color(status.Level.String())), st.Style(status.Message))

	}

}
